package com.djl.zenithbite.service.shopping.food.impl;

import com.djl.zenithbite.common.response.BaseResponse;
import com.djl.zenithbite.dto.request.FoodAddRequest;
import com.djl.zenithbite.entity.*;
import com.djl.zenithbite.repository.*;
import com.djl.zenithbite.service.shopping.food.FoodService;
import com.djl.zenithbite.util.check.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
public class FoodServiceImpl implements FoodService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private TagRelationMapper tagRelationMapper;

    @Autowired
    private ProductCategoryMapper productCategoryMapper;

    @Autowired
    private ProductCategoryRelationMapper productCategoryRelationMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseResponse<Product> addFood(FoodAddRequest request) {
        Product product = buildProduct(request);
        product.setProductId(null);
        product.setCreatedAt(new Date());
        product.setUpdatedAt(new Date());

        productMapper.insertSelective(product);

        List<Integer> tagList = request.getTagList();
        Optional.ofNullable(tagList).orElse(new ArrayList<>()).forEach(tag ->{
            Tag tag1 = tagMapper.selectByPrimaryKey(tag);
            AssertUtil.notNull(tag1,"tag not exist");

            TagRelation tagRelation = new TagRelation();
            tagRelation.setTagId(tag);
            tagRelation.setEntityId(product.getProductId());
            tagRelation.setEntityType(tag1.getTagType());

            tagRelationMapper.insertSelective(tagRelation);
        });

        List<Integer> categoryList = request.getCategoryList();
        Optional.ofNullable(categoryList).orElse(new ArrayList<>()).forEach(category ->{
            ProductCategory existProductCategory = productCategoryMapper.selectByPrimaryKey(category);
            AssertUtil.notNull(existProductCategory,"productCategory not exist");

            ProductCategoryRelation productCategoryRelation = new ProductCategoryRelation();
            productCategoryRelation.setCategoryId(category);
            productCategoryRelation.setProductId(product.getProductId());
            productCategoryRelation.setCreatedAt(new Date());

            productCategoryRelationMapper.insertSelective(productCategoryRelation);
        });

        BaseResponse<Product> response = new BaseResponse<>();
        response.setData(product);
        response.setCode(BaseResponse.SUCCESS);
        return response;
    }

    private Product buildProduct(FoodAddRequest request) {
        Product product = new Product();
        product.setProductId(request.getProductId());
        product.setStoreId(request.getStoreId());
        product.setProductName(request.getProductName());
        product.setProductPrice(request.getProductPrice());
        product.setOriginalPrice(request.getOriginalPrice());
        product.setImageUrl(request.getImageUrl());
        product.setCategoryId(request.getCategoryId());
        product.setStock(request.getStock());
        product.setStatus(request.getStatus());
        product.setIsRecommended(request.getIsRecommended());
        product.setProductDesc(request.getProductDesc());
        return product;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseResponse<Product> edit(FoodAddRequest request) {
        Product existProduct = productMapper.selectByPrimaryKey(request.getProductId());
        AssertUtil.notNull(existProduct, "product not exist");

        Product product = buildProduct(request);
        product.setUpdatedAt(new Date());

        productMapper.updateByPrimaryKeySelective(product);

        if (!CollectionUtils.isEmpty(request.getTagList())){

            TagRelationExample example = new TagRelationExample();
            TagRelationExample.Criteria criteria = example.createCriteria();
            criteria.andEntityIdEqualTo(product.getProductId());
            tagRelationMapper.deleteByExample(example);

            List<Integer> tagList = request.getTagList();
            Optional.ofNullable(tagList).orElse(new ArrayList<>()).forEach(tag ->{
                Tag tag1 = tagMapper.selectByPrimaryKey(tag);
                AssertUtil.notNull(tag1,"tag not exist");

                TagRelation tagRelation = new TagRelation();
                tagRelation.setTagId(tag);
                tagRelation.setEntityId(product.getProductId());
                tagRelation.setEntityType(tag1.getTagType());

                tagRelationMapper.insertSelective(tagRelation);
            });
        }

        if (CollectionUtils.isEmpty(request.getCategoryList())){
            ProductCategoryRelationExample productCategoryRelationExample = new ProductCategoryRelationExample();
            ProductCategoryRelationExample.Criteria criteria = productCategoryRelationExample.createCriteria();
            criteria.andProductIdEqualTo(product.getProductId());
            productCategoryRelationMapper.deleteByExample(productCategoryRelationExample);


            List<Integer> categoryList = request.getCategoryList();
            Optional.ofNullable(categoryList).orElse(new ArrayList<>()).forEach(category ->{
                ProductCategory existProductCategory = productCategoryMapper.selectByPrimaryKey(category);
                AssertUtil.notNull(existProductCategory,"productCategory not exist");

                ProductCategoryRelation productCategoryRelation = new ProductCategoryRelation();
                productCategoryRelation.setCategoryId(category);
                productCategoryRelation.setProductId(product.getProductId());
                productCategoryRelation.setCreatedAt(new Date());

                productCategoryRelationMapper.insertSelective(productCategoryRelation);
            });
        }

        BaseResponse<Product> response = new BaseResponse<>();
        response.setCode(BaseResponse.SUCCESS);
        response.setData(product);
        return response;
    }

    @Override
    public BaseResponse<List<Product>> list(Integer storeId) {
        ProductExample example = new ProductExample();
        ProductExample.Criteria criteria = example.createCriteria();
        criteria.andStoreIdEqualTo(storeId);

        List<Product> products = productMapper.selectByExampleWithBLOBs(example);

        BaseResponse<List<Product>> response = new BaseResponse<>();
        response.setData(products);
        response.setCode(BaseResponse.SUCCESS);

        return response;
    }
}
